#pragma once
#include<iostream>
#include<semaphore.h>
#include<pthread.h>
#include<vector>



namespace ns_ring_queue
{
    const int default_cap = 5;

    template<class T>
    class ring_queue
    {
    private:
        int _cap;
        std::vector<T> _rq;
        sem_t _blank_sem; 
        sem_t _data_sem;

        int c_sem;
        int p_sem;

        pthread_mutex_t p_mutex;
        pthread_mutex_t c_mutex;
        
        public:
        ring_queue(int cap = default_cap)
        :_cap(cap),_rq(cap)
        {
            //初始化
            sem_init(&_blank_sem,0,_cap);
            sem_init(&_data_sem,0,0);
            c_sem = p_sem = 0;
            pthread_mutex_init(&p_mutex,nullptr);
            pthread_mutex_init(&c_mutex,nullptr);

        }

        ~ring_queue()
        {
            sem_destroy(&_blank_sem);
            sem_destroy(&_data_sem);
            pthread_mutex_destroy(&p_mutex);
            pthread_mutex_destroy(&c_mutex);
        }

    public:
        void Push(const T& in)
        {
            //空位置--
            sem_wait(&_blank_sem);
            pthread_mutex_lock(&p_mutex);
             _rq[p_sem] = in;

            p_sem++;
             p_sem %= _cap;
             pthread_mutex_unlock(&p_mutex);
             //数据位置++
            sem_post(&_data_sem); 

        }
        void Pop(T* out)
        {
            sem_wait(&_data_sem); //数据位置--
            pthread_mutex_lock(&c_mutex);
            *out = _rq[c_sem];
            c_sem++;
            c_sem %= _cap;
            pthread_mutex_unlock(&c_mutex);
            sem_post(&_blank_sem) ; // 空位置++

        }

    
    };
}